# _*_ coding:utf-8 _*_
# @File  : app.py
# @Time  : 2021-07-13 15:52
# @Author: zizle

import threading
from fastapi import FastAPI, Request
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from fastapi.exceptions import StarletteHTTPException, RequestValidationError
from configs import FILE_STORAGE
from middlewares import middleware
from interfaces import interface_api
from adminapi import admin_api_router
from v1_all_api import v1_all_api
from db import FAConnection

from logger import logger
from tasks import task_scheduler

from global_constant import VARIETY, USERS

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
# 注册pdf字符
pdfmetrics.registerFont(TTFont('SyH_N', 'ttf/SourceHanSansCN-Normal.ttf'))  # 注册字体
pdfmetrics.registerFont(TTFont('SyH_B', 'ttf/SourceHanSansCN-Bold.ttf'))


app = FastAPI()


@app.on_event('startup')
def create_app():
    mount_static()            # 挂载静态文件
    add_middleware()          # 添加中间件
    add_exception_handlers()  # 全局错误处理
    add_routers()             # 添加路由
    # start_background_tasks()  # 后台线程任务
    set_global_data()         # 设置全局数据


def mount_static():
    app.mount("/static/", StaticFiles(directory=FILE_STORAGE), name="staticFiles")


def add_middleware():
    # 自定义中间件
    app.add_middleware(middleware.AdminAuthMiddleware)  # 验证管理员
    # 添加框架中有的中间件 allow_credentials=True允许携带cookie，此时allow_origins不能为["*"]
    app.add_middleware(CORSMiddleware, allow_origins=['*'], allow_credentials=False, allow_methods=["*"],
                       allow_headers=['*'])


def add_exception_handlers():
    app.add_exception_handler(RequestValidationError, handler=request_validation_exception)
    app.add_exception_handler(StarletteHTTPException, handler=http_exception_handler)
    app.add_exception_handler(Exception, handler=all_exception_handler)


async def request_validation_exception(request: Request, exc: RequestValidationError):
    print('HTTP: 422 Error: {}'.format(request.url))
    print(exc.errors())
    return JSONResponse(
        content={'success': False, 'message': ';\n'.join([i['msg'] for i in jsonable_encoder(exc.errors())])},
        status_code=422
    )


async def http_exception_handler(request: Request, exc: StarletteHTTPException):
    print('HTTP: {} Error: {}'.format(request.url, exc.detail))
    return JSONResponse(
        content={'success': False, 'message': exc.detail, 'code': exc.status_code},
        status_code=exc.status_code
    )


async def all_exception_handler(request: Request, exc: Exception):
    print('URL: {} Error: {}'.format(request.url, exc))
    return JSONResponse(
        content={'success': False, 'message': '服务器发生了错误！', 'code': 500},
        status_code=500
    )


def add_routers():
    # 添加api接口路由
    app.include_router(interface_api, prefix='/api')
    # 后台接口(因为是后期添加,所有仅包含部分,有时间可将其他也整理/重写进去)
    app.include_router(admin_api_router, prefix='/admin')

    # 新版网页版接口,版本1
    app.include_router(v1_all_api, prefix='/v1')


def start_background_tasks():
    logger.info('创建每日执行定时任务的线程')
    t = threading.Thread(target=task_scheduler.threading_task_scheduler)
    t.setDaemon(True)
    t.start()
    logger.info('创建定时任务线程成功!')


# 设置全局数据
def set_global_data():
    db_conn = FAConnection()
    variety = db_conn.query("SELECT variety_en,variety_name FROM ruizy_variety WHERE is_active=1;", keep_conn=True)
    VARIETY.VARIETY_NAMES = {v['variety_en']: v['variety_name'] for v in variety}  # 设置品种数据
    department_users = db_conn.query('SELECT id,admin_name FROM ruizy_user WHERE role_code>=3000;')
    USERS.DEPARTMENT_NAMES = {u['id']: u['admin_name'] for u in department_users}


